import type { ComponentStyleIdType } from '../../types/interfaces'
import type { TableColumn, TableData, TableProps } from './types'
import { UIComponent } from '../../lib/abstract'
import { HtmlEntity } from '../../lib/html_entity'
import { ComponentStyleId, PROJECT_PREFIX } from '../../types/constants'
import { SearchBox } from '../search'
import { Select } from '../select'
import { styles } from './styles'
import { DEFAULT_TABLE_PROPS } from './types'

export class Table extends UIComponent<TableProps> {
  id: string = 'table'
  readonly description: string = '表格组件'
  readonly styleId: string = ComponentStyleId[this.name]
  private searchBox: SearchBox | null = null
  private columnSelect: Select | null = null
  private originalData: TableData[] = []
  private filteredData: TableData[] = []

  get name(): ComponentStyleIdType {
    return 'Table'
  }

  get className(): string {
    return 'custom-table'
  }

  constructor(props: TableProps) {
    super({
      ...DEFAULT_TABLE_PROPS,
      ...props,
    })

    this.originalData = [...props.data]
    this.filteredData = [...props.data]
    this.registerStyles()
  }

  ELEMENT_SELECTORS = {
    table: { selector: `#${this.props.id}`, dynamic: false, unique: true },
    searchContainer: { selector: '.table-search-container', dynamic: false, unique: true },
  }

  /**
   * 渲染表格组件
   */
  render(): string {
    const { id, title, columns, showIndex, indexWidth, maxHeight, showDataCount } = this.props

    return `
      <div class="${this.className}">
        ${title ? `<h3 class="table-title">${title}</h3>` : ''}
        ${showDataCount ? this.renderDataCount() : ''}
        <div class="table-search-container"></div>
        <div class="table-responsive" style="${maxHeight !== 'auto' ? `max-height: ${maxHeight}; overflow-y: auto;` : ''}">
          <table id="${id}" class="table-data">
            <thead>
              <tr>
                ${showIndex ? `<th style="width: ${indexWidth}">序号</th>` : ''}
                ${columns.map((col: TableColumn) => {
                  const styles = this.getColumnStyle(col)
                  const styleContent = styles.length ? `style="${styles}"` : ''
                  return `<th ${styleContent}>${col.title}</th>`
                }).join('')}
              </tr>
            </thead>
            <tbody>
              ${this.renderTableBody(this.filteredData)}
            </tbody>
          </table>
        </div>
      </div>
    `
  }

  /**
   * 渲染数据量统计
   */
  private renderDataCount(): string {
    const total = this.originalData.length
    const filtered = this.filteredData.length
    const isFiltered = total !== filtered

    return `
      <div class="table-data-count">
        共 ${total} 条数据${isFiltered ? `，筛选后 ${filtered} 条` : ''}
      </div>
    `
  }

  /**
   * 获取列样式
   */
  private getColumnStyle(col: TableColumn): string {
    const styles: string[] = []

    if (col.width) {
      styles.push(`width: ${col.width}`)
    }
    if (col.minWidth) {
      styles.push(`min-width: ${col.minWidth}`)
    }
    if (col.maxWidth) {
      styles.push(`max-width: ${col.maxWidth}`)
    }

    return styles.join('; ')
  }

  /**
   * 渲染表格内容
   */
  private renderTableBody(data: TableData[]): string {
    const { columns, showIndex } = this.props
    const keyword = this.searchBox?.getValue()?.trim() || ''
    const columnKey = this.columnSelect?.getValue()

    return data.map((row, index) => `
    <tr>
      ${showIndex ? `<td class="index-column">${index + 1}</td>` : ''}
      ${columns.map((col: TableColumn) => {
        const cellValue = row[col.key] || ''
        let displayValue = col.render
          ? col.render(row[col.key], row)
          : String(cellValue)

        // 只在搜索时高亮
        if (keyword && (!columnKey || columnKey === col.key)) {
          displayValue = this.highlightMatch(displayValue, keyword)
        }

        return `<td data-column="${col.key}">${displayValue}</td>`
      }).join('')}
    </tr>
  `).join('')
  }

  /**
   * 初始化搜索和过滤功能
   */
  private initSearchAndFilter(): void {
    const { id, columns, onSearch } = this.props
    const $searchContainer = this.$element?.find('.table-search-container')

    // 初始化搜索框
    this.searchBox = new SearchBox({
      id: `${id}-search`,
      placeholder: '搜索表格内容...',
      debounceTime: 300,
      onSearch: (keyword) => {
        this.filterData(keyword.trim(), this.columnSelect?.getValue())
        onSearch?.(keyword.trim(), this.filteredData)
      },
    })

    // 初始化列选择下拉框
    this.columnSelect = new Select({
      id: `${id}-column-select`,
      label: '搜索列',
      options: columns.map((col: TableColumn) => ({
        label: col.title,
        value: col.key,
      })),
      showPlaceholder: true,
      placeholder: '全部列',
      clearable: true,
      onChange: (selectedColumn) => {
        const keyword = this.searchBox?.getValue() || ''
        this.filterData(keyword, selectedColumn)
      },
    })

    // 渲染搜索组件
    $searchContainer?.html(`
      <div class="table-controls">
        <div class="search-container">
          ${this.searchBox.render()}
        </div>
        <div class="select-container">
          ${this.columnSelect.render()}
        </div>
      </div>
    `)

    if (!$searchContainer || !$searchContainer.length)
      return

    this.searchBox.mount($searchContainer)
    this.columnSelect.mount($searchContainer)
  }

  /**
   * 过滤表格数据
   */
  private filterData(keyword: string, columnKey?: string): void {
    if (!keyword) {
      this.filteredData = [...this.originalData]
    }
    else {
      const lowerKeyword = keyword.toLowerCase()

      this.filteredData = this.originalData.filter((row) => {
        // 指定列搜索
        if (columnKey) {
          const column = this.props.columns.find((col: TableColumn) => col.key === columnKey)

          // 使用自定义搜索函数
          if (column?.searchFn) {
            return column.searchFn(row[columnKey], row, lowerKeyword)
          }

          // 默认搜索逻辑
          return String(HtmlEntity.decode(row[columnKey])).toLowerCase().includes(lowerKeyword)
        }

        // 全局搜索逻辑
        return Object.entries(row).some(([key, value]) => {
          const column = this.props.columns.find((col: TableColumn) => col.key === key)

          // 使用自定义搜索函数
          if (column?.searchFn) {
            return column.searchFn(value, row, lowerKeyword)
          }

          // 默认搜索逻辑
          return String(HtmlEntity.decode(value)).toLowerCase().includes(lowerKeyword)
        })
      })
    }

    this.updateTableBody()
    this.updateDataCount()
  }

  /**
   * 设置搜索列
   */
  setSearchColumn(columnKey: string): void {
    const cleanedText = columnKey.trim()

    if (!cleanedText || cleanedText.length === 0)
      return

    this.columnSelect?.setValue(columnKey)
  }

  /**
   * 设置搜索文本
   */
  setSearchText(text: string): void {
    const cleanedText = text.trim()

    if (!cleanedText || cleanedText.length === 0)
      return

    this.searchBox?.setValue(cleanedText)
  }

  /**
   * 更新表格内容
   */
  private updateTableBody(): void {
    const { id } = this.props
    const $tbody = $(`#${id} tbody`)
    $tbody.html(this.renderTableBody(this.filteredData))
  }

  /**
   * 更新数据统计显示
   */
  private updateDataCount(): void {
    if (this.props.showDataCount) {
      const $container = $(`#${this.props.id}`).closest(`.${this.className}`)
      $container.find('.table-data-count').replaceWith(this.renderDataCount())
    }
  }

  /**
   * 更新表格数据（同时更新数据统计）
   */
  updateData(newData: TableData[]): void {
    this.originalData = [...newData]
    this.filteredData = [...newData]
    this.updateTableBody()
    // 应用过滤
    this.filterData(this.searchBox?.getValue() || '', this.columnSelect?.getValue())
  }

  /**
   * 高亮匹配文本（支持HTML实体高亮）
   * @param text 原始文本
   * @param keyword 搜索关键词
   * @returns 带有高亮标记的HTML字符串
   * @description 测试字符串：g（是 &gt; HTML实体的一部分）、>、问题
   */
  private highlightMatch(text: string, keyword: string): string {
    if (!text || !keyword)
      return text

    // 解码HTML实体后的关键词（用于匹配实体内容）
    const escapedKeyword = this.escapeRegExp(keyword)
    const isEntyty = HtmlEntity.isEntity(keyword)

    // 分割文本为HTML标签、实体和纯文本三部分
    const parts = text.split(/(<[^>]+>|&[a-z]{2,6};)/)

    return parts.map((part) => {
      // 1. 跳过普通HTML标签
      if (/^<[^>]+>$/.test(part)) {
        return part
      }

      // 2. 处理HTML实体（如 &gt; &lt;）
      if (/^&[a-z]{2,6};$/.test(part)) {
        // 检查实体是否匹配关键词（比较解码后的实体）
        const decodedEntity = HtmlEntity.decode(part)
        if (isEntyty && (decodedEntity.includes(keyword) || part.includes(keyword))) {
          return this.createHighlightSpan(part)
        }
        return part
      }

      // 3. 处理纯文本部分
      const combinedRegex = new RegExp(`(${escapedKeyword})`, 'gi')
      return part.replace(combinedRegex, match => this.createHighlightSpan(match))
    }).join('')
  }

  /**
   * 创建高亮标签
   */
  private createHighlightSpan(content: string): string {
    const backgroundColor = `var(--${PROJECT_PREFIX}-theme-table-highlight-bg)`
    return `
      <span class="table-highlight" style="
        color: #ffffff !important;
        background-color: ${backgroundColor} !important;"
        >
        ${content}
      </span>
    `
  }

  /**
   * 转义正则特殊字符（支持处理HTML实体）
   */
  private escapeRegExp(str: string): string {
    return str.replace(/[.*+?^${}()|[\]\\&<>;]/g, '\\$&')
  }

  /**
   * 绑定事件
   */
  bindEvents(): void {
    this.initSearchAndFilter()
  }

  /**
   * 获取组件样式
   */
  getStyles(): string {
    return styles(this.className)
  }

  /**
   * 销毁组件
   */
  destroy(): void {
    super.destroy()
    this.searchBox?.destroy()
    this.columnSelect?.destroy()
  }
}
